import json
from ..utils.config import REAGENT_FILE, LOCK_FILE, INJECT_FILE
from .snail_fun import Snail
from ..utils.simple_logging import get_app_logger
from .shared import stop_event
import threading
from pathlib import Path
import time

# 获取机器控制日志记录器
logger = get_app_logger("machine_control")

# 初始化泵
snail = Snail()

# 加载JSON文件(返回JSON数据)
def load_json_file(file_path, file_name):
    """
    加载 JSON 文件并返回数据。
    
    :param file_path: 文件路径 (字符串或 Path 对象)
    :param file_name: 文件名 (用于日志记录)
    :return: JSON 数据 或 None (如果加载失败)
    """
    if isinstance(file_path, Path):
        file_path = str(file_path)

    try:
        with open(file_path, "r", encoding="utf-8") as file:
            data = json.load(file)
        logger.info(f"成功加载 {file_name}: {file_path}")
        return data
    except Exception as e:
        logger.error(f"错误: 加载 {file_name} 失败 - {e}")
        return None

def reset():
    logger.info("开始执行 reset()")
    snail.pump.reset()
    logger.info("完成 reset()")
    
    # 重置时清除停止事件
    stop_event.clear()
    logger.info("停止事件已清除")

def wash_tube():
    logger.info("开始执行 wash_tube()")
    snail.wash()
    logger.info("完成 wash_tube()")

def empty_tube():
    logger.info("开始执行 empty_tube()")
    snail.empty_tube()
    logger.info("完成 empty_tube()")

def fill_tube(reagent2=None):
    logger.info("开始执行 fill_tube()")
    snail.fill_tube(reagent2=reagent2)
    logger.info("完成 fill_tube()")

def reaction(INJECT_FILE, REAGENT_FILE, stop_event, system_state):
    """
    根据传入的 INJECT_FILE 和 REAGENT_FILE 执行反应步骤，支持暂停/继续功能
    
    :param INJECT_FILE: 包含反应步骤的 JSON 文件路径
    :param REAGENT_FILE: 包含试剂映射的 JSON 文件路径
    :param stop_event: 用于控制流程停止的事件对象
    :param system_state: 系统状态对象
    """
    logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
    logger.info("开始反应流程")

    # 加载试剂映射文件
    reagent_data = load_json_file(REAGENT_FILE, "试剂映射文件")
    if not reagent_data:
        logger.error("无法继续流程，因试剂映射文件加载失败")
        return
    reagent_to_port = {item["reagent"]: item["port"] for item in reagent_data}
    
    # 加载反应步骤文件
    raw_steps = load_json_file(INJECT_FILE, "反应步骤文件")
    if not raw_steps:
        logger.error("无法继续流程，因反应步骤文件加载失败")
        return

    # 转换为字典格式
    inject_steps = {}
    for step in raw_steps:
        reagent_name = step.get("reagent")
        if reagent_name not in reagent_to_port:
            logger.error(f"错误: 未找到试剂 {reagent_name} 对应的端口号")
            continue
        port = reagent_to_port[reagent_name]
        inject_steps[step["index"]] = (
            port,
            step["cycles"],
            step["timewait"],
            step["temperature"],
            reagent_name  # 添加试剂名称用于日志显示
        )
    
    # 获取排序后的步骤索引
    sorted_indexes = sorted(inject_steps.keys())
    
    # 从保存的状态恢复（如果是从暂停继续）
    start_index = system_state.current_step_index
    cycle_count = system_state.current_cycle_count
    
    if start_index > 0:
        logger.info(f"从暂停点继续执行: 步骤 {start_index} (已完成 {cycle_count} 次循环)")
        # 显示暂停状态信息
        if start_index in inject_steps:
            port, times, timewait, temperature, reagent_name = inject_steps[start_index]
            logger.info(f"当前步骤详情: 试剂={reagent_name}, 端口={port}, 总循环={times}, 已完成={cycle_count}")
    else:
        logger.info("开始新的反应流程")
    
    # 更新系统状态，标记反应开始
    system_state.device_status = 'reacting'
    system_state.save_state()
    
    try:
        # 遍历步骤
        for step_idx, idx in enumerate(sorted_indexes):
            if idx < start_index:
                continue  # 跳过已完成的步骤
                
            port, times, timewait, temperature, reagent_name = inject_steps[idx]
            
            # 更新当前步骤索引
            system_state.current_step_index = idx
            system_state.current_step_info = f"步骤 {idx}: {reagent_name}"
            system_state.save_state()
            
            logger.info(f"开始执行步骤 {idx}: 试剂={reagent_name}, 端口={port}, 循环次数={times}")
            
            # 从保存的循环计数开始（仅适用于从暂停恢复的情况）
            start_cycle = cycle_count if idx == start_index else 0
            
            for i in range(start_cycle, times):
                # 检查停止请求
                if stop_event.is_set():
                    logging.warning("检测到停止标志，终止反应流程")
                    system_state.device_status = 'idle'
                    system_state.current_step_index = 0
                    system_state.current_cycle_count = 0
                    system_state.save_state()
                    return
                    
                # 检查暂停请求 - 在每个操作之前检查
                if system_state.reaction_paused:
                    logger.info(f"反应流程已暂停")
                    logger.info(f"暂停位置: 步骤 {idx} - {reagent_name} (第 {i+1}/{times} 次循环)")
                    logger.info(f"下一个动作: 抽取试剂 {reagent_name} 并注入反应腔")
                    
                    system_state.current_cycle_count = i
                    system_state.device_status = 'paused'
                    system_state.save_state()
                    
                    # 等待暂停状态结束
                    while system_state.reaction_paused:
                        if stop_event.is_set():
                            logging.warning("检测到停止标志，终止反应流程")
                            system_state.device_status = 'idle'
                            system_state.current_step_index = 0
                            system_state.current_cycle_count = 0
                            system_state.save_state()
                            return
                        time.sleep(1)  # 每秒检查一次
                    
                    # 从暂停恢复
                    logger.info(f"从暂停恢复，继续执行步骤 {idx} - {reagent_name} (第 {i+1}/{times} 次循环)")
                    system_state.device_status = 'reacting'
                    system_state.save_state()
                
                # 执行注入操作 - 每个单独的泵操作都可以被暂停
                logger.info(f"执行步骤 {idx} 第 {i+1}/{times} 次循环: 抽取试剂 {reagent_name}")
                
                system_state.next_action_info = f"注入 {reagent_name} (循环 {i+1}/{times})"
                system_state.save_state()
                # 执行实际的注入操作
                snail.inject(
                    reagent=port,
                    times=1,
                    timewait=timewait,
                    temperature=temperature,
                    stop_event=stop_event,          # 新增
                    system_state=system_state  
                )
                
                logger.info(f"完成步骤 {idx} 第 {i+1}/{times} 次循环")
                
                # 更新当前循环计数
                system_state.current_cycle_count = i + 1
                system_state.save_state()
                
                # 在每次循环之间也检查暂停
                if system_state.reaction_paused:
                    logger.info(f"反应流程已暂停")
                    logger.info(f"暂停位置: 步骤 {idx} - {reagent_name} (已完成 {i+1}/{times} 次循环)")
                    if i + 1 < times:
                        logger.info(f"下一个动作: 继续试剂 {reagent_name} 的第 {i+2} 次循环")
                    else:
                        next_step_idx = step_idx + 1
                        if next_step_idx < len(sorted_indexes):
                            next_idx = sorted_indexes[next_step_idx]
                            next_reagent = inject_steps[next_idx][4]
                            logger.info(f"下一个动作: 开始步骤 {next_idx} - {next_reagent}")
                        else:
                            logger.info("下一个动作: 反应流程完成")
                    
                    system_state.current_cycle_count = i + 1
                    system_state.device_status = 'paused'
                    system_state.save_state()
                    
                    while system_state.reaction_paused:
                        if stop_event.is_set():
                            logging.warning("检测到停止标志，终止反应流程")
                            system_state.device_status = 'idle'
                            system_state.current_step_index = 0
                            system_state.current_cycle_count = 0
                            system_state.save_state()
                            return
                        time.sleep(1)
                    
                    logger.info(f"从暂停恢复")
                    system_state.device_status = 'reacting'
                    system_state.save_state()
            
            # 完成当前步骤，重置循环计数
            system_state.current_cycle_count = 0
            system_state.save_state()
            logger.info(f"完成步骤 {idx}: {reagent_name}")
            
            # 重置 start_index 相关的 cycle_count，确保下一步从头开始
            cycle_count = 0
    
    except Exception as e:
        logger.error(f"反应流程执行出错: {e}")
        system_state.device_status = 'error'
        system_state.save_state()
        return
    
    # 完成后重置状态
    system_state.current_step_index = 0
    system_state.current_cycle_count = 0
    system_state.device_status = 'idle'
    system_state.save_state()
    logger.info("反应流程完成")

def force_clear():
    logger.info("开始执行 force_clear()")
   
    # 设置速度
    snail.pump.set_speed(speed=800)
    snail.pump.move_pump_to_zero()
    
    # 从3号空气管道抽取空气，依次排空所有管道
    snail.pump.set_speed(speed=1000)
    snail.pump.move_and_aspirate(volume=10000, port_number=2)
    snail.pump.move_and_dispense(volume=5000, port_number=1)
    snail.pump.move_and_dispense(volume=5000, port_number=3)
    
    snail.pump.set_speed(speed=1000)
    snail.pump.move_and_aspirate(volume=10000, port_number=2)
    snail.pump.move_and_dispense(volume=5000, port_number=4)
    snail.pump.move_and_dispense(volume=5000, port_number=5)
    
    snail.pump.set_speed(speed=1000)
    snail.pump.move_and_aspirate(volume=10000, port_number=2)
    snail.pump.move_and_dispense(volume=5000, port_number=6)
    snail.pump.move_and_dispense(volume=5000, port_number=7)
    
    snail.pump.set_speed(speed=1000)
    snail.pump.move_and_aspirate(volume=10000, port_number=2)
    snail.pump.move_and_dispense(volume=5000, port_number=8)
    snail.pump.move_and_dispense(volume=5000, port_number=9)
    
    logger.info("完成 force_clear()")